/*
 *  SlopeMap.h
 *  SlopeMap
 *
 *  Created by Shing Yip on 3/15/08.
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef SlopeMap_h
#define SlopeMap_h

#include <algorithm>

template <typename ValueT, bool BounceCheck = false>
class SlopeMap {
public:
    typedef ValueT slope_type;

    SlopeMap(int dim)
      : dim_(dim) 
    {
        slopes_ = new slope_type[dim_*(dim_ - 1)/2];
    }
    
    SlopeMap(const SlopeMap& right)
      : dim_(right.dim_) 
    {
        slopes_ = new slope_type[dim_];
        for (int i = 0; i < dim_; ++i) {
            slopes_[i] = right.slopes_[i];
        }
    }

    ~SlopeMap() {
        delete [] slopes_;
    }
    
    SlopeMap& operator=(const SlopeMap& right) {
        SlopeMap tmpCopy(right);
        swap(tmpCopy);
    }

    void swap(SlopeMap& other) {
        std::swap(dim_, other.dim_);
        std::swap(slopes_, other.slopes_);
    }
    
    slope_type slope(int orig, int dest) const {
        if (dest < orig) {
            return slopes_[index(orig, dest)];
        } else if (orig < dest) {
            return -slopes_[index(dest, orig)];
        } else {
            return slope_type();
        }
    }
    
    void setSlope(int orig, int dest, slope_type value) {
        if (BounceCheck) {
            if (!(orig < dim_ && dest < dim_)) {
                throw std::range_error("setSlope out of range");
            }
        }
        
        if (dest < orig) {
            slopes_[index(orig, dest)] = value;
        } else if (orig < dest) {
            slopes_[index(dest, orig)] = -value;
        }        
    }
    
private:
    // dest must always be smaller than orig
    int index(int orig, int dest) const {
        return orig*(orig+1)/2 - orig + dest;
    }

private:
    int dim_;
    slope_type* slopes_;
};


#endif // SlopeMap_h
